package net.example.lesson5.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

/**
 * @author ${user}
 * @version V1.0
 * @Title: ${file_name}
 * @Package ${package_name}
 * @Description: ${todo}(用一句话描述该文件做什么)
 * @date ${date}
 */
public class NIOService implements Runnable {
    //1 多路复用器（管理所有的通道）
    private Selector seletor;
    //2 建立缓冲区
    private final ByteBuffer readBuf = ByteBuffer.allocate(1024);

    public NIOService(int port) {
        try {
            //1 打开路复用器
            this.seletor = Selector.open();
            //2 打开服务器通道
            final ServerSocketChannel ssc = ServerSocketChannel.open();
            //3 设置服务器通道为非阻塞模式
            ssc.configureBlocking(false);
            //4 绑定地址
            ssc.bind(new InetSocketAddress(port));
            //5 把服务器通道注册到多路复用器上，并且监听阻塞事件
            ssc.register(this.seletor, SelectionKey.OP_ACCEPT);

            System.out.println("Server start, port :" + port);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                //1 必须要让多路复用器开始监听
                this.seletor.select();
                //2 返回多路复用器已经选择的结果集
                final Iterator<SelectionKey> keys = this.seletor.selectedKeys().iterator();
                //3 进行遍历
                while (keys.hasNext()) {
                    SelectionKey key = keys.next();
                    sayHelloWorld((ServerSocketChannel)key.channel());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private void sayHelloWorld(ServerSocketChannel server) throws IOException {
        try (final SocketChannel client = server.accept();) {
            client.write(Charset.defaultCharset().encode("Hello world!"));
        }
    }

    public static void main(String[] args) {
        new Thread(new NIOService(8765)).start();
    }
}
